package com.flyme.common.security.filter;

import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by xinxingegeya on 2017/5/17.
 */
public class AbstractDispatchFilter extends OncePerRequestFilter {
    // Used to determine which chain should handle an incoming request/response
    private FilterChainResolver filterChainResolver;

    public AbstractDispatchFilter() {
    }

    public FilterChainResolver getFilterChainResolver() {
        return filterChainResolver;
    }

    public void setFilterChainResolver(FilterChainResolver filterChainResolver) {
        this.filterChainResolver = filterChainResolver;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        executeChain(request, response, filterChain);
    }

    /**
     * Executes a {@link FilterChain} for the given request.
     *
     * @param request   the incoming HttpServletRequest
     * @param response  the outgoing HttpServletResponse
     * @param origChain the Servlet Container-provided chain that may be wrapped further by an application-configured
     *                  chain of Filters.
     * @throws IOException      if the underlying {@code chain.doFilter} call results in an IOException
     * @throws ServletException if the underlying {@code chain.doFilter} call results in a ServletException
     */
    protected void executeChain(HttpServletRequest request, HttpServletResponse response, FilterChain origChain)
            throws IOException, ServletException {
        FilterChain chain = getExecutionChain(request, response, origChain);
        chain.doFilter(request, response);
    }

    /**
     * Returns the {@code FilterChain} to execute for the given request.
     *
     * @param request   the incoming HttpServletRequest
     * @param response  the outgoing HttpServletResponse
     * @param origChain the original {@code FilterChain} provided by the Servlet Container
     * @return the {@link FilterChain} to execute for the given request
     */
    protected FilterChain getExecutionChain(HttpServletRequest request, HttpServletResponse response, FilterChain origChain) {
        FilterChain chain = origChain;
        FilterChainResolver resolver = getFilterChainResolver();
        if (resolver == null) {
            return origChain;
        }
        FilterChain resolved = resolver.getChain(request, response, origChain);
        if (resolved != null) {
            chain = resolved;
        }
        return chain;
    }
}
